/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.classes.controller;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.validation.Valid;

import org.springblade.common.constant.RedisKeyConstant;
import org.springblade.common.exception.TrainingServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.classes.entity.ClassesPlanEntity;
import org.springblade.modules.classes.entity.ClassesUserEntity;
import org.springblade.modules.classes.entity.TrainingPlanCourseEntity;
import org.springblade.modules.classes.entity.TrainingPlanEntity;
import org.springblade.modules.classes.excel.*;
import org.springblade.modules.classes.service.IClassesPlanService;
import org.springblade.modules.classes.service.IClassesUserService;
import org.springblade.modules.classes.service.ITrainingPlanCourseService;
import org.springblade.modules.classes.service.ITrainingPlanService;
import org.springblade.modules.classes.vo.TrainingPlanCourseVO;
import org.springblade.modules.classes.vo.TrainingPlanVO;
import org.springblade.modules.classes.wrapper.TrainingPlanCourseWrapper;
import org.springblade.modules.classes.wrapper.TrainingPlanWrapper;
import org.springblade.modules.course.entity.CourseChapterEntity;
import org.springblade.modules.course.entity.CourseChapterSubEntity;
import org.springblade.modules.course.entity.CourseEntity;
import org.springblade.modules.course.service.ICourseChapterService;
import org.springblade.modules.course.service.ICourseChapterSubService;
import org.springblade.modules.course.service.ICourseService;
import org.springblade.modules.course.vo.CourseVO;
import org.springblade.modules.log.service.IIntegralTrainingLogService;
import org.springblade.modules.personal.entity.UserBaseEntity;
import org.springblade.modules.personal.service.IUserBaseService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.excel.util.ExcelUtil;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

/**
 * 培训计划表 控制器
 *
 * @author junxin
 * @since 2023-04-26
 */
@RestController
@AllArgsConstructor
@RequestMapping("blade-trainingPlan/trainingPlan")
@Api(value = "培训计划表", tags = "培训计划表接口")
public class TrainingPlanController extends BladeController {

	private final IIntegralTrainingLogService integralTrainingLogService;
	private final ITrainingPlanService trainingPlanService;
	private final ITrainingPlanCourseService trainingPlanCourseService;
	private final ICourseService courseService;
	private final ICourseChapterService courseChapterService;
	private final ICourseChapterSubService courseChapterSubService;
	private final IClassesPlanService classesPlanService;
	private final IClassesUserService classesUserService;
	private final IUserBaseService userBaseService;
	private final BladeRedis bladeRedis;

	/**
	 * 培训计划表 详情
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入trainingPlan")
	public R detail(TrainingPlanEntity trainingPlan) {
		TrainingPlanEntity detail = trainingPlanService.getOne(Condition.getQueryWrapper(trainingPlan));
		TrainingPlanVO trainingPlanVO = TrainingPlanWrapper.build().entityVO(detail);

		//获取该培训计划的 培训计划课程 并根据课程节点升序
		List<TrainingPlanCourseEntity> trainingPlanCourseList = trainingPlanCourseService.list(Wrappers.<TrainingPlanCourseEntity>query().lambda()
			.eq(TrainingPlanCourseEntity::getTrainingPlanId, detail.getId()).orderByAsc(TrainingPlanCourseEntity::getSort));

		//给每条培训计划设置对应的课程列表值
		if (CollectionUtil.isNotEmpty(trainingPlanCourseList)) {
			List<CourseVO> courseVOList = trainingPlanCourseList.stream().map(trainingPlanCourseEntity -> {

				//课程设置
				CourseEntity courseEntity = courseService.getById(trainingPlanCourseEntity.getCourseId());
				CourseVO courseVO = new CourseVO();
				if (null == courseEntity) {
					return courseVO;
				}
				BeanUtil.copyProperties(courseEntity, courseVO);
				courseVO.setIsExam(trainingPlanCourseEntity.getIsExam());
				courseVO.setChapters(courseChapterService.count(Wrappers.<CourseChapterEntity>query().lambda().eq(CourseChapterEntity::getCourseId, trainingPlanCourseEntity.getCourseId())));
				courseVO.setSubs(courseChapterSubService.count(Wrappers.<CourseChapterSubEntity>query().lambda().eq(CourseChapterSubEntity::getCourseId, trainingPlanCourseEntity.getCourseId())));

				TrainingPlanCourseVO trainingPlanCourseVO = TrainingPlanCourseWrapper.build().entityVO(trainingPlanCourseEntity);
				trainingPlanCourseVO.setCourseName(courseEntity.getName());

				return courseVO;
			}).collect(Collectors.toList());
			trainingPlanVO.setCourseList(courseVOList);

			trainingPlanVO.setTrainingPlanCourseList(trainingPlanCourseList.stream().map(trainingPlanCourseEntity -> {
				TrainingPlanCourseVO trainingPlanCourseVO=new TrainingPlanCourseVO();
				BeanUtil.copyProperties(trainingPlanCourseEntity,trainingPlanCourseVO);
				return  trainingPlanCourseVO;
			}).collect(Collectors.toList()));
		}
		return R.data(trainingPlanVO);
	}

	/**
	 * 培训计划表 分页
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入trainingPlan")
	public R<IPage<TrainingPlanVO>> list(@ApiIgnore @RequestParam Map<String, Object> trainingPlan, Query query) {
		IPage<TrainingPlanEntity> pages = trainingPlanService.page(Condition.getPage(query), Condition.getQueryWrapper(trainingPlan, TrainingPlanEntity.class));
		IPage<TrainingPlanVO> trainingPlanVOIPage = TrainingPlanWrapper.build().pageVO(pages);
		//设置培训计划的相关课程
//		List<Long> trainPlanIds=trainingPlanVOIPage.getRecords().stream().map(TrainingPlanVO::getId).collect(Collectors.toList());
//		trainingPlanVOIPage.setRecords(trainingPlanService.trainingPlanDetail(trainPlanIds,trainingPlanVOIPage.getRecords()));
		return R.data(trainingPlanVOIPage);
	}


	/**
	 * 培训计划表 新增
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入trainingPlan")
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public R save(@Valid @RequestBody TrainingPlanVO trainingPlan) {
		if (StringUtils.isBlank(trainingPlan.getYear())) throw new TrainingServiceException("请输入年度");
		trainingPlanService.save(trainingPlan);
		List<TrainingPlanCourseVO> trainingPlanCourseList = trainingPlan.getTrainingPlanCourseList();
		if (CollectionUtil.isNotEmpty(trainingPlanCourseList)) {
			List<TrainingPlanCourseEntity> trainingPlanCourseEntityList = trainingPlanCourseList.stream().map(planCourseVO -> {
				TrainingPlanCourseEntity planCourseEntity = new TrainingPlanCourseEntity();
				BeanUtil.copyProperties(planCourseVO, planCourseEntity);
				planCourseEntity.setTrainingPlanId(trainingPlan.getId());
				return planCourseEntity;
			}).collect(Collectors.toList());
			trainingPlanCourseService.saveBatch(trainingPlanCourseEntityList);
		}
		return R.success("操作成功");
	}

	/**
	 * 培训计划表 修改
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入trainingPlan")
	@Transactional(rollbackFor = Exception.class)
	public R update(@Valid @RequestBody TrainingPlanVO trainingPlan) {
		//删除原有的培训计划
		trainingPlanCourseService.remove(Wrappers.<TrainingPlanCourseEntity>query().lambda().
			eq(TrainingPlanCourseEntity::getTrainingPlanId,trainingPlan.getId()));
		List<TrainingPlanCourseVO> trainingPlanCourseList = trainingPlan.getTrainingPlanCourseList();
		if (CollectionUtil.isNotEmpty(trainingPlanCourseList)) {
			List<TrainingPlanCourseEntity> trainingPlanCourseEntityList = trainingPlanCourseList.stream().map(planCourseVO -> {
				TrainingPlanCourseEntity planCourseEntity = new TrainingPlanCourseEntity();
				BeanUtil.copyProperties(planCourseVO, planCourseEntity,"id");
				planCourseEntity.setTrainingPlanId(trainingPlan.getId());
				return planCourseEntity;
			}).collect(Collectors.toList());
			trainingPlanCourseService.saveBatch(trainingPlanCourseEntityList);
		}
		return R.status(trainingPlanService.updateById(trainingPlan));
	}


	/**
	 * 培训计划表 删除
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	@Transactional(rollbackFor = Exception.class)
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		trainingPlanCourseService.deleteByPlanIds(Func.toLongList(ids));
		return R.status(trainingPlanService.deleteLogic(Func.toLongList(ids)));
	}

	@PostMapping("import-year")
	@ApiOperationSupport(order = 18)
	@ApiOperation(value = "导入年度计划", notes = "传入classesId")
	public R importQuestionBank(MultipartFile file) {
		TrainingPlanYearImporter trainingPlanYearImporter = new TrainingPlanYearImporter(bladeRedis,integralTrainingLogService,userBaseService);
		ExcelUtil.save(file, trainingPlanYearImporter, TrainingYearExcel.class);
		return R.success("操作成功");
	}

	/**
	 * 导出模板
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("export-template")
	@ApiOperationSupport(order = 19)
	@ApiOperation(value = "导出模板")
	public void exportUser(HttpServletResponse response) {
		List<TrainingYearExcel> list = new ArrayList<>();
		ExcelUtil.export(response, "年度计划数据模板", "年度计划表", list, TrainingYearExcel.class);
	}

	/**
	 * 下拉列表
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/select")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "下拉列表", notes = "传入trainingPlan")
	public R select(@ApiIgnore @RequestParam Map<String, Object> entity) {
		QueryWrapper<TrainingPlanEntity> queryWrapper = Condition.getQueryWrapper(entity, TrainingPlanEntity.class);
		return R.data(trainingPlanService.list(queryWrapper));
	}


	/**
	 * 导出培训结果
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/export-result")
	@ApiOperationSupport(order = 21)
	@ApiOperation(value = "导出培训结果", notes = "传入trainingPlan")
	public void exportTrainingPlan(@ApiParam(value = "主键集合", required = true) @RequestParam String ids, HttpServletResponse response) {
		//获取培训计划
		List<TrainingPlanEntity> trainingPlanList = trainingPlanService.listByIds(Func.toLongList(ids));
		List<TrainingPlanReusltExcel> list = new ArrayList<>();
		trainingPlanList.forEach(plan -> {
			List<ClassesPlanEntity> classesPlanEntityList = classesPlanService.list(Wrappers.<ClassesPlanEntity>query().lambda().eq(ClassesPlanEntity::getPlanId, plan.getId()));
			if (CollectionUtil.isEmpty(classesPlanEntityList)) return;
			classesPlanEntityList.forEach(classesPlan -> {

				//查询该班级的下学生
				List<ClassesUserEntity> userList = classesUserService.list(Wrappers.<ClassesUserEntity>query().lambda()
					.eq(ClassesUserEntity::getClassesId, classesPlan.getClassesId()));
				if (CollectionUtil.isEmpty(userList)) return;

				//查询该培训计划的课程
				List<TrainingPlanCourseEntity> planCourseList = trainingPlanCourseService.list(Wrappers.<TrainingPlanCourseEntity>query().lambda()
					.eq(TrainingPlanCourseEntity::getTrainingPlanId, classesPlan.getPlanId()));
				if (CollectionUtil.isEmpty(planCourseList)) return;

				for (ClassesUserEntity user : userList) {
					boolean flag;
					String result = "通过";
					for (TrainingPlanCourseEntity planCourse : planCourseList) {
						flag = courseService.checkCourseComplete(planCourse.getCourseId(), user.getUserId());
						if (!flag) {
							result = "不通过";
							break;//如果有一门课程不通过，则表示所有都不通过
						}
					}

					TrainingPlanReusltExcel excel = new TrainingPlanReusltExcel();
					excel.setResult(result);
					excel.setPlanName(plan.getPlanName());
					UserBaseEntity userBase = userBaseService.getOne(Wrappers.<UserBaseEntity>query()
						.lambda().eq(UserBaseEntity::getUserId, user.getUserId()));
					if (null != userBase) {
						excel.setUserName(userBase.getUserName());
						excel.setIdCard(userBase.getIdCard());
					}
					list.add(excel);
				}

			});

		});
		ExcelUtil.export(response, "培训结果数据" + DateUtil.time(), "培训结果", list, TrainingPlanReusltExcel.class);
	}

	@GetMapping("/compare")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = "年度培训年计划对照", notes = "传入trainingPlan")
	public R TrainingPlanCompare() {
		String year= DateUtil.format(new Date(), "yyyy");
		List<TrainingYearExcel> trainPlanList = bladeRedis.get(RedisKeyConstant.TRAINING_PLAN_YEAR +year);

		LocalDateTime startTime=LocalDateTime.of(Integer.parseInt(year),1,1,0,0,0);
		LocalDateTime endTime=LocalDateTime.of(Integer.parseInt(year),12,31,23,59,59);
		List<TrainingPlanEntity> beginingPlanList = trainingPlanService.list(Wrappers.<TrainingPlanEntity>query().lambda()
			.eq(TrainingPlanEntity::getYear, year)
			);//今年已开展的培训计划
		List<TrainingYearExcel> beginingPlans = beginingPlanList.stream().map(begining -> {
			TrainingYearExcel excel = new TrainingYearExcel();
			excel.setPlanTrainingMessage(begining.getPlanName());
			excel.setYear(year);
			return excel;
		}).collect(Collectors.toList());

		TrainingYearVo vo=new TrainingYearVo();
		List<TrainingYearExcel> beginingList=new ArrayList<>();//已开展的培训计划
		List<TrainingYearExcel> waitList=new ArrayList<>(); // 待开展的培训计划

		if (CollectionUtils.isNotEmpty(trainPlanList)){
			trainPlanList.forEach(trainingYear->{
				if (beginingPlans.contains(trainingYear)) {
					beginingList.add(trainingYear);
				}else {
					waitList.add(trainingYear);
				}
			});
		}

		vo.setBeginingList(beginingList);
		vo.setWaitList(waitList);

		return R.data(vo);
	}
}
